//********************************************************
// Board.java 
// Date: 4/18/2012
// Author: Andrew Landphier
//********************************************************
// Creates a grid of jpanels within an application window. The JPanels respond
// to user input via right click action events. The board is initialized with a
// defined set of enabled panels, which allow a popup to occur, based off the 
// number of players. The state of the board is kept in the BoardState.java class and
// any of the alterations to the board panels happen here.
//*******************************************************
// EDITED by Jeff:
//*******************************************************

package ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;

import java.awt.GridLayout;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.filechooser.FileFilter;

import driver.Driver;

import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

import ui.data.BoardState;
import ui.listener.PopupListener;

import functionality.Player;
import functionality.Point;


public class Board extends BoardState implements Serializable {
	public static Color light_green = new Color(143,188,143);
	public static Color indian_red = new Color(170,143,143);
	private static int iSize;
	public static JFrame frame;
	public static JInternalFrame framex ;
	public ArrayList<String> stats=new ArrayList<String>();
	public static JPanel[][] grid;
	public static JTextArea textT;
	public static JPanel hand;
	
	/**
	 * Create the board for the specified number of players
	 * @param iPlayer number of players 2-4
	 * @return none
	 */	
	public Board(int iPlayer) {
		super(iPlayer);
	}
	
	/**
	 * Open the board and set it visible
	 * @param none
	 * @return none
	 */
	public void Open(){
		iSize = super.iBoardSize;
		frame=new JFrame("RobberKnights");
		frame.setBounds(100, 100, 95*iSize, 88*iSize);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);
		initialize();
		
		
		framex.setPreferredSize(new Dimension( 76*iSize, 77*iSize));
		framex.setVisible(true);
		textT = new JTextArea(3,3);
		//textT.setBackground(Driver.currentPlayer.getColor());
		hand=new JPanel();
	
		getStats();
		frame.getContentPane().add(framex, BorderLayout.CENTER);
		frame.getContentPane().add(hand, BorderLayout.EAST);

		JMenuBar menuBar = new JMenuBar();


		menuBar.setSize(200, 350);	  


		JMenu fileMenu = new JMenu("File");
		JMenu helpMenu = new JMenu("Help");

		JMenuItem newAction =   new JMenuItem("New Game");
		JMenuItem exitAction =  new JMenuItem("Exit");
		
		JMenuItem rulesAction =  new JMenuItem("Rules");
		JMenuItem aboutAction= new JMenuItem("About RobberKnights");
		
		newAction.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				
				try {
					restart();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
		
		exitAction.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				
				
				System.exit(0);
			}
		});
		rulesAction.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				JFrame r=new JFrame("Rules");
				JPanel p=new JPanel();		
				JLabel rules1=new JLabel(new ImageIcon("ICONS/Gamerules.png"));
				JLabel rules2=new JLabel(new ImageIcon("ICONS/Gamerules_01.png"));
				JLabel rules3=new JLabel(new ImageIcon("ICONS/Gamerules_02.png"));
				JLabel rules4=new JLabel(new ImageIcon("ICONS/Gamerules_03.png"));
				
				p.add(rules1);
				p.add(rules2);
				p.add(rules3);
				p.add(rules4);
				p.setVisible(true);				
				p.add(rules1);
				JScrollPane scrollBar=new JScrollPane(p,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
				
				r.getContentPane().add(scrollBar);				
				r.pack();					
				r.setDefaultCloseOperation(r.DISPOSE_ON_CLOSE);
				r.setVisible(true);
			
			}
		});
		aboutAction.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				JFrame r=new JFrame("About");
				JPanel p=new JPanel();	
				JTextArea t = new JTextArea(11,3);
				t.setFont(new Font("Serif", Font.ITALIC, 20));
				
				t.setBackground(Color.LIGHT_GRAY);
				t.setForeground(Color.WHITE);
				t.setEditable(false);						
				
				t.append(" " + "\n");
				t.append("       "+ "Robber Knights "+ "\n");
				t.append("       "+"Build: Spring 2012 "+ "\n");
				t.append("____________________ " + "\n");
				t.append("       "+" *Authors* "+ "\n");
				t.append(" " + "\n");
				t.append("       "+" Chris C "+ "\n");
				t.append("       "+"Andrew L "+ "\n");
				t.append("       "+"Jason L "+ "\n");
				t.append("       "+"Mark T "+ "\n");
				t.append("       "+"Jeff X "+ "\n");					
				
				p.setVisible(true);				
				p.add(t, BorderLayout.NORTH);				
				
			
				r.getContentPane().add(p, BorderLayout.CENTER);
				r.pack();					
				r.setDefaultCloseOperation(r.DISPOSE_ON_CLOSE);
				r.setResizable(false);
				r.setVisible(true);
				
			
			}
		});
		
		fileMenu.add(newAction);	
		fileMenu.addSeparator();
		fileMenu.add(exitAction);		
		helpMenu.add(rulesAction); 
		helpMenu.addSeparator();
		helpMenu.add(aboutAction); 	
		  
		menuBar.add(fileMenu);
	
		menuBar.add(helpMenu);
		menuBar.setVisible(true);
		frame.setJMenuBar(menuBar);		
		
		frame.setVisible(true);
	}
	
	/**
	 * Close the board
	 * 
	 * @param none
	 * @return none
	 */
	public void getStats(){
		
		ArrayList<Tile> t=Driver.b.getAllTiles();
		int points=0;
		for(Tile t2:t)
		{
			if(t2.getTopKnight().equals(Driver.getCurrentPlayer().getColor()))
			{
				points+=t2.getWorth();
			}
		}
		
		textT = new JTextArea(3,3);
		textT.setFont(new Font("Serif", Font.ITALIC, 15));
		textT.setBackground(Driver.getCurrentPlayer().getColor());
		//textT.setBackground(Color.BLACK);
		//textT.setForeground(Color.WHITE);
		textT.setEditable(false);		
		
		
		textT.append(" Player "+Driver.getCountTurns()+ "\n");
		textT.append(" Knights left: "+Driver.getCurrentPlayer().getNumKnights()+" Deck"+ "\n");
		
		if(Driver.getCurrentPlayer().getNumCards()>0)
		{
			textT.append(" Tiles left:  "+Driver.getCurrentPlayer().getNumCards()+" Deck"+ "\n");
		}
		else if(Driver.getCurrentPlayer().getNumCards()<=0)
		{
			textT.append(" Tiles left: 0" + "\n");
		}
		
		textT.append(" Points:  "+points+ "\n");
		textT.setVisible(true);
		hand.removeAll();
		hand.add(textT, BorderLayout.NORTH);
		hand.setPreferredSize(new Dimension(150, 100));
		
		hand.revalidate();
		hand.setVisible(true);
		frame.getContentPane().add(hand, BorderLayout.EAST);
		frame.revalidate();

		
		
	}
	
		
	/**
	 * Close the board
	 * 
	 * @param none
	 * @return none
	 */
	public void close(){
		frame.dispose();
		//System.exit(0);
	}

	/**
	 * restart the game
	 * 
	 * @param none
	 * @return none
	 * @throws IOException 
	 * @throws FileNotFoundException 
	 */
	public void restart() throws IOException{
		frame.dispose();			  
	
		try {
			Runtime.getRuntime().exec("java -jar robberknights.jar");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.exit(0);
		
	}
	
	/**
	 * Diable the board
	 * 
	 * @param none
	 * @return none
	 */
	public void disable(){
		frame.setEnabled(false);
	}

	/**
	 * Enable the board
	 * 
	 * @param none
	 * @return none
	 */
	public void enable(){
		frame.setEnabled(true);
		frame.requestFocus();
	}

	/**
	 * Initialize the contents of the frame. Pass in the number of players to load the correct board size.
	 * 
	 * @param iSize the size of the border to be created
	 * @return none
	 */
	private void initialize() {
		
		framex = new JInternalFrame("", false);
		framex.setBorder(null);		
		framex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		framex.getContentPane().setLayout(new CardLayout(0, 0));
		JPanel panel = new JPanel();
		framex.getContentPane().add(panel, "main_panel");
		panel.setLayout(new GridLayout(0, iSize, 0, 0));
	
		
		//Create compound border for the tiles
		//*** Note didn't look into the different styles
		Border blackborder;
		blackborder = BorderFactory.createLineBorder(Color.BLACK);

		//PopupListener to be added to all the game panels
		PopupListener popupListener = new PopupListener();

		//Create the grid object with the appropriate size
		grid = new JPanel[iSize][iSize];

		//Add the panels to the grid layout
		Integer x, y;
		for (x=0; x < iSize; x++ ){
			for (y=0; y < iSize; y++){
				grid[x][y] = new JPanel();
				grid[x][y].setBorder(blackborder);
				grid[x][y].setLayout(new GridLayout());
				grid[x][y].addMouseListener(popupListener);
				grid[x][y].setEnabled(false);
				grid[x][y].setBackground(indian_red);
				
				//Initialize 2x2 board green and enabled
				if (Board.numplayers == 2) {
					if (checkTwoPlayerBoard(x,y)) {
						grid[x][y].setEnabled(true);
						grid[x][y].setBackground(light_green);
					}
					
				//Initialize 2x3 board green and enabled
				} else if (Board.numplayers == 3) {
					if (checkThreePlayerBoard(x,y)) {
						grid[x][y].setEnabled(true);
						grid[x][y].setBackground(light_green);
					}
				
				//Initialize 2x4 board green and enabled
				} else if (Board.numplayers == 4) {
					if (checkFourPlayerBoard(x,y)) {
						grid[x][y].setEnabled(true);
						grid[x][y].setBackground(light_green);
					}
				} 
				panel.add(grid[x][y]);
			}
		}

		
		
	}
	

	public static void setAdjacentBackground(int x, int y){
		int icase = 0;icase = y-1; // TODO couldnt these 2 lines be combined into just one?
		if (icase >= 0) {
			if (getTile(new Point(x,icase)) == 0) {
				grid[x][icase].setBackground(light_green); // left
				grid[x][icase].setEnabled(true);
			}
		}
		
		icase = x-1;
		if (icase >= 0){
			if (getTile(new Point(icase,y)) == 0) {
				grid[icase][y].setBackground(light_green); // up
				grid[icase][y].setEnabled(true);
			}
		}
		
		icase = y+1;
		if (icase <= iSize-1){
			if (getTile(new Point(x,icase)) == 0) {
				grid[x][icase].setBackground(light_green); // right
				grid[x][icase].setEnabled(true);
			}
		}
		
		icase = x+1;
		if (icase <= iSize-1){
			if (getTile(new Point(icase,y)) == 0) {
				grid[icase][y].setBackground(light_green); // down
				grid[icase][y].setEnabled(true);
			}
		}
	}
	
	/**
	 * Expand the valid board places upon filling up the initial "starting" orientation of the board. 
	 * Initial conditions checked via BoardState (checkInitialBoardState(p)
	 * 
	 * @param none
	 * @return none
	 */
	public static void oneTimeBoardExpand(){
		int x,y;
	
		for (x=0; x < iSize; x++ ){
			for (y=0; y < iSize; y++){
				if (Board.numplayers == 2) {
					if (checkTwoPlayerBoard(x,y)) {
						setAdjacentBackground(x,y);
					}
				} else if (Board.numplayers == 3) {
					if (checkThreePlayerBoard(x,y)) {
						setAdjacentBackground(x,y);
					}
				} else if (Board.numplayers == 4) {
					if (checkFourPlayerBoard(x,y)) {
						setAdjacentBackground(x,y);
					}
				}
			}
		}
	}
	
	/**
	 * Disable the source panel at the given point
	 * 
	 * @param p point
	 * @return none
	 */
	public static void disablePanel(Point p){
		grid[p.getX()][p.getY()].setEnabled(false);
	}
	
	/**
	 * Return size of grid panel
	 * 
	 * @return int size of board
	 */
	public int getISize(){
		return iSize;
	}
	
	public JPanel getGrid(int x, int y)
	{
		return grid[x][y];
	}
	
	public boolean boardIsEnabled()
	{
		return frame.isEnabled();
	}
}